home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d20
/
makearc3.arc
/
MAKEARC2.C
< prev
Wrap
Text File
|
1990-12-04
|
22KB
|
877 lines
/* MakeArc copyright (c) 1990 by M. Kimes -- All Rights Reserved */
/* Version 204 You can use this freely. Check with me before */
/* releasing modified executables or source, please (I'll probably */
/* allow it). Exceptions: Strict translation to foreign languages */
/* and ports to other platforms (non-IBMPC-compatible). */
/* Corrections, bug reports, etc. welcome. Flames ignored by a */
/* master. */
/* Include files; a couple of TC specific here... */
#include <conio.h>
#include <dir.h>
#include <time.h>
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <ctype.h>
#include <process.h>
#include <string.h>
/* Couple of typedefs */
typedef unsigned int word;
typedef unsigned bit;
/* Message header */
struct _msg {
char from[36];
char to[36];
char subj[72];
char date[20];
word times;
word dest;
word orig;
word cost;
word orig_net;
word dest_net;
int msg_filler[4];
word reply;
word attr;
word up;
};
/* Message attributes */
#define MSGPRIVATE 0x0001
#define MSGCRASH 0x0002
#define MSGREAD 0x0004
#define MSGSENT 0x0008
#define MSGFILE 0x0010
#define MSGFWD 0x0020
#define MSGORPHAN 0x0040
#define MSGKILL 0x0080
#define MSGLOCAL 0x0100
#define MSGXX1 0x0200
#define MSGXX2 0x0400
#define MSGFRQ 0x0800
#define MSGRRQ 0x1000
#define MSGCPT 0x2000
#define MSGARQ 0x4000
#define MSGURQ 0x8000
/* Packet header */
struct _pkthdr { /* Mostly copied from JoHo. I like JoHo. */
word
orig_node, /* originating node */
dest_node, /* destination node */
year, /* 1989 - nnnnn */
month, /* 1-12 (note all this wasted space!) */
day, /* 1-31 */
hour, /* 0-23 */
minute, /* 0-59 */
second, /* 0-60 */
rate, /* unused */
ver, /* always 2 */
orig_net, /* originating net */
dest_net; /* destination net */
char
product, /* product code */
rev_lev, /* revision level */
password[8];
word
qm_orig_zone, /* BARF! */
qm_dest_zone; /* BARF! */
char TRASH[8]; /* Domain? */
word
orig_zone, /* originating zone */
dest_zone, /* destination zone */
orig_point, /* originating point */
dest_point; /* destination point */
long pr_data;
};
/* Global flags and variables */
extern char msgattach; /* Make *.MSG attaches? */
extern word myzone; /* For our address */
extern word mynet; /* " */
extern word mynode; /* " */
extern word mypoint; /* " */
extern char configfile[133]; /* Config file to read */
extern char root[128]; /* 'Root' outbound dir */
extern char outbound[133]; /* Extended outbound dir */
extern char netdir[128]; /* Net msg directory if *.MSG attaches */
extern char arccmd[128]; /* Default archive command */
extern char alltype; /* Default mail type */
extern char didbreak; /* CTRL-BREAK flag */
extern char schedtag[128]; /* Schedule tag */
extern word lines; /* For debug info */
extern char debug; /* debug on? */
extern char more; /* more on? */
extern char usingbink; /* Use BINKLEY.CFG? */
extern word rzone; /* For routing */
extern word rnet; /* " */
extern word rnode; /* " */
extern word rpoint; /* " */
/* Function definitions */
char pascal spawnit (char *a);
char pascal check_4flo (word zone,word net,word node,word point);
char * pascal stristr (char *t, char *s);
void cdecl deinit(void);
void pascal say_error (long lastpos,FILE *fp);
int pascal makearc (char *arcfile,char *pktfile,char *origpkt,char *outbound);
word pascal makeflo(word zone,word net,word node,word point,char *sendfile,char type);
word pascal makemessage (word zone,word net,word node,word point,char *sendfile,char type);
void pascal next_name(char *);
void pascal make_poll (char *line,long lastpos,FILE *fp);
FILE * pascal analyze(char *);
char * pascal arcname(word,word);
char * pascal filename(word,word);
char * pascal fidodate(void);
char * pascal lstrip(char *);
char * pascal rstrip(char *);
char * pascal stripcr(char *);
int cdecl break_handler(void);
void pascal moveit (struct ffblk *f, char *myoutbound, char *outbound, char type, char archive,word net,word node,word fromzone);
void pascal move_prep(char *line,long lastpos,FILE *fp);
void pascal change_mail(char *line,long lastpos,FILE *fp);
long pascal make_msgid(void);
char * pascal find_sched(FILE *fp,char *schedtag,int wholefile);
char * pascal skip_white(char *);
char * pascal skip_nonwhite(char *);
char * pascal to_delim(char *,char *);
int cdecl hardware_error (int errnum,int ax,int bp,int si);
/* ID stuff */
#define MAKEVER "204"
#define PID_ID "MA 204"
#define BETA
void pascal move_prep (char *line,long lastpos,FILE *fp) {
char flo[133]; /* Used to find (& destroy) flo files */
char arc[133]; /* Used to find arc files */
char pkt[133]; /* Used to find packets */
unsigned int zone,net,node; /* Address to move to */
unsigned int fromzone; /* Zone to move mail from */
char outbound[84]; /* His calculated outbound name */
struct ffblk f; /* The better to find them with, my dearie */
char *p; /* Used to parse address */
char type; /* Type of mail ([H]old, [C]rash, etc.) */
lstrip(line);
stripcr(line);
rstrip(line);
p=strtok(line," ");
if(!p) return;
fromzone=(word)atol(p);
if(!fromzone) return;
p=strtok(0,":");
if(!p) return;
zone=(word)atol(p);
if(zone==fromzone) return; /* Duh... */
if(!zone) return;
p=strtok(0,"/");
if(!p) return;
net=(word)atol(p);
if(!net) return;
p=strtok(0," ");
if(!p) return;
node=(word)atol(p);
p=strtok(0,";\n");
type=toupper(*p);
if(type!='H' && type!='C' && type!='F' && type!='D' && type!='N' && type!='O') return;
/* Make mask for outbound flo, packet and arc files */
if(fromzone!=myzone) {
sprintf(pkt,"%s.%03x\\%04x%04x.?UT",root,fromzone,net,node);
sprintf(arc,"%s.%03x\\%04x%04x.*",root,fromzone,mynet-net,mynode-node);
sprintf(flo,"%s.%03x\\%04x%04x.?LO",root,fromzone,net,node);
}
else {
sprintf(pkt,"%s\\%04x%04x.?UT",root,net,node);
sprintf(arc,"%s\\%04x%04x.*",root,mynet-net,mynode-node);
sprintf(flo,"%s\\%04x%04x.?LO",root,net,node);
}
if(zone!=myzone) sprintf(outbound,"%s.%03x",root,zone);
else strcpy(outbound,root);
if(!findfirst(flo,&f,0)) {
printf("Removing FLO files addressed to %u:%u/%u\n",fromzone,net,node);
do {
if(fromzone==myzone) sprintf(flo,"%s\\%s",root,f.ff_name);
else sprintf(flo,"%s.%03x\\%s",root,fromzone,f.ff_name);
unlink(flo);
} while(!findnext(&f));
}
if(!findfirst(pkt,&f,0)) {
if(fromzone==myzone) {
moveit(&f,root,outbound,type,0,net,node,fromzone);
}
else {
sprintf(flo,"%s.%03x",root,fromzone);
moveit(&f,flo,outbound,type,0,net,node,fromzone);
}
}
if(!findfirst(arc,&f,0)) {
if(fromzone==myzone)moveit(&f,root,outbound,type,1,net,node,fromzone);
else {
sprintf(flo,"%s.%03x",root,fromzone);
moveit(&f,flo,outbound,type,0,net,node,fromzone);
}
}
return;
}
void pascal moveit (struct ffblk *f, char *myoutbound, char *outbound, char type, char archive,word net,word node,word fromzone) {
union REGS r;
struct SREGS sregs;
FILE *fp=NULL;
FILE *fp2;
char once=0;
char wasname[133];
char isname[133];
if(archive) { /* If archive, open flo file for append */
sprintf(wasname,"%s\\%04x%04x.%cLO",outbound,net,node,type);
fp=fopen(wasname,"at");
if(fp)fseek(fp,0L,SEEK_END);
}
do {
if(f->ff_fsize==0L) continue;
if(!once){
if(archive)printf("Moving archived mail addressed to %u:%u/%u\n",fromzone,net,node);
else printf("Moving packets addressed to %u:%u/%u\n",fromzone,net,node);
}
once=1;
sprintf(wasname,"%s\\%s",myoutbound,f->ff_name);
sprintf(isname,"%s\\%s",outbound,f->ff_name);
if(!archive)isname[strlen(isname)-3]=type; /* Set mail type */
r.h.ah=0x56;
r.x.dx=FP_OFF(wasname);
sregs.ds=FP_SEG(wasname);
r.x.di=FP_OFF(isname);
sregs.es=FP_SEG(isname);
int86x(0x21,&r,&r,&sregs); /* Move 'em */
if(archive) { /* Only for archives */
fp2=fopen(wasname,"wb");
if(fp2)fclose(fp2); /* Leave truncated filename */
if(fp) fprintf(fp,"^%s\n",isname); /* Add name to the flo file */
}
} while(!findnext(f)); /* Til there ain't no more */
if(fp) {
fseek(fp,0L,SEEK_END);
if(ftell(fp)==0L) {
fclose(fp);
sprintf(wasname,"%s\\%04x%04x.%cLO",outbound,net,node,type);
unlink(wasname);
}
else fclose(fp);
}
}
void pascal change_mail (char *line,long lastpos,FILE *fp) {
unsigned int zone,net,node; /* Address to change mail type for */
char flo[133];
/* char req[133]; */
char pkt[133];
char outbound[84];
struct ffblk f;
struct ffblk f1;
char *p;
char type;
char s[133];
char s1[133];
FILE *infile=NULL;
FILE *outfile;
unsigned int bytes;
lstrip(line);
stripcr(line);
rstrip(line);
zone=myzone;
net=0;
node=0;
printf("!!!%s!!!\n",line);
if(!strnicmp(line,"ALL ",4)) { /* This doesn't work yet; don't use it */
p=line+4;
lstrip(p);
printf("!!!%s!!!\n",p);
if(!strnicmp(p,"ZONE ",5)) {
p+=5;
lstrip(p);
printf("!!!%s!!!\n",p);
zone=(word)atol(p);
if(!zone) {
fprintf(stderr,"\nZero Zone #\n");
say_error(lastpos,fp);
return;
}
}
if(strchr(p,' ')) {
p=strchr(p,' ');
p++;
type=*p;
}
else type=alltype;
p=NULL;
}
else {
p=strtok(line,":");
if(!p) {
fprintf(stderr,"\nMissing Zone\n");
say_error(lastpos,fp);
return;
}
zone=(word)atol(p);
if(!zone) {
fprintf(stderr,"\nZero Zone\n");
say_error(lastpos,fp);
return;
}
p=strtok(0,"/");
if(!p) {
fprintf(stderr,"\nMissing Net\n");
say_error(lastpos,fp);
return;
}
net=(word)atol(p);
if(!net) {
fprintf(stderr,"\nZero Net\n");
say_error(lastpos,fp);
return;
}
p=strtok(0," ");
if(!p) {
fprintf(stderr,"\nMissing Node\n");
say_error(lastpos,fp);
return;
}
node=(word)atol(p);
p=strtok(0,"; \n");
if(!p) type=alltype;
else type=toupper(*p);
}
if(type!='H' && type!='C' && type!='F' && type!='D' && type!='N' && type!='O') {
fprintf(stderr,"\nInvalid mail type `%c'\n",type);
say_error(lastpos,fp);
return;
}
/* Make mask for outbound flo, packet and arc files */
if(zone!=myzone)sprintf(outbound,"%s.%03x",root,zone);
else strcpy(outbound,root);
if(net)sprintf(pkt,"%s\\%04x%04x.?UT",outbound,net,node);
else sprintf(pkt,"%s\\*.?UT",outbound);
/* Removed the following since Bink 2.40 no longer forces call for REQ */
/* Left the code in in case you need it */
/* if(type!='H')sprintf(req,"%s\\%04x%04x.HEQ",outbound,net,node);
else sprintf(req,"%s\\%04x%04x.REQ",outbound,net,node); */
if(net)sprintf(flo,"%s\\%04x%04x.?LO",outbound,net,node);
else sprintf(flo,"%s\\*.?LO",outbound);
if(!findfirst(pkt,&f,0)) {
if(type=='F') type='N';
sprintf(s,"%s\\%s",outbound,f.ff_name);
s[strlen(s)-3]=type;
if(net)printf("Changing flavor of %u:%u:%01u's mail to %c\n",zone,net,node,type);
else printf("Changing flavor of Zone #%u's mail to %c\n",zone,type);
do {
if(infile==NULL) {
if(!findfirst(s,&f1,0)) {
if(f1.ff_fsize==0L) unlink(s);
else {
infile=fopen(s,"r+b");
if(!infile) {
fprintf(stderr,"\nCan't open \'%s\'\n",s);
break;
}
fseek(infile,f.ff_fsize-4L,SEEK_SET);
while((char)fgetc(infile)!='\0' && !feof(infile)); /* Should be right after first of last NULLs */
}
}
}
if(f.ff_name[9]!=type) {
sprintf(s1,"%s\\%s",outbound,f.ff_name);
if(!infile)rename(s1,s);
else {
outfile=fopen(s1,"rb");
if(!outfile) {
fprintf(stderr,"\nCan't open \'%s\'\n",s1);
fclose(infile);
infile=NULL;
break;
}
fseek(outfile,(long)sizeof(struct _pkthdr),SEEK_SET); /* skip header to 1st msg */
while (!feof(outfile)) {
bytes=fread(s1,1,133,outfile);
fwrite(s1,1,bytes,infile);
if(bytes!=133) break;
}
fclose(outfile);
}
}
} while(!findnext(&f));
}
if(infile)fclose(infile);
if(!findfirst(flo,&f,0)) {
if(type=='N' || type=='O') type='F';
sprintf(s,"%s\\%s",outbound,f.ff_name);
s[strlen(s)-3]=type;
if(net)printf("Changing flavor of %u:%u:%01u's attach(es) to %c\n",zone,net,node,type);
else printf("Changing flavor of Zone #%u's attach(es) to %c\n",zone,type);
do {
if(infile==NULL) {
if(!findfirst(s,&f1,0)) {
/* if(f1.ff_fsize==0L) unlink(s);
else {
*/ infile=fopen(s,"r+b");
if(!infile) {
fprintf(stderr,"\nCan't open \'%s\'\n",s);
break;
}
fseek(infile,0L,SEEK_END);
/* } */
}
}
if(f.ff_name[9]!=type) {
sprintf(s1,"%s\\%s",outbound,f.ff_name);
if(!infile)rename(s1,s);
else {
outfile=fopen(s1,"rb");
if(!outfile) {
fprintf(stderr,"\nCan't open \'%s\'\n",s1);
fclose(infile);
infile=NULL;
break;
}
fseek(outfile,0L,SEEK_SET);
while (!feof(outfile)) {
bytes=fread(s1,1,133,outfile);
fwrite(s1,1,bytes,infile);
if(bytes!=133) break;
}
fclose(outfile);
}
}
} while(!findnext(&f));
}
if(infile)fclose(infile);
/* if(!findfirst(req,&f,0)) {
sprintf(s,"%s\\%s",outbound,f.ff_name);
if(type=='H')s[strlen(s)-3]='H';
else {
type='R';
s[strlen(s)-3]='R';
}
if(net)printf("Changing flavor of %u:%u:%01u's REQ(s) to %c\n",zone,net,node,type);
else printf("Changing flavor of Zone #%u's REQ(s) to %c\n",zone,type);
do {
if(infile==NULL) {
if(!findfirst(s,&f1,0)) {
if(f1.ff_fsize==0L) unlink(s);
else {
infile=fopen(s,"r+b");
if(!infile) {
fprintf(stderr,"\nCan't open \'%s\'\n",s);
break;
}
fseek(infile,0L,SEEK_END);
}
}
}
if(f.ff_name[9]!=type) {
sprintf(s1,"%s\\%s",outbound,f.ff_name);
if(!infile)rename(s1,s);
else {
outfile=fopen(s1,"rb");
if(!outfile) {
fprintf(stderr,"\nCan't open \'%s\'\n",s1);
fclose(infile);
infile=NULL;
break;
}
fseek(outfile,0L,SEEK_SET);
while (!feof(outfile)) {
bytes=fread(s1,1,133,outfile);
fwrite(s1,1,bytes,infile);
if(bytes!=133) break;
}
fclose(outfile);
}
}
} while(!findnext(&f));
}
if(infile)fclose(infile);
*/
}
void pascal make_poll (char *line,long lastpos,FILE *pf) {
char *p;
/* char *pw; */
word zone,net,node;
/* word point; */
/* FILE *fp; */
char s[133];
/* struct _pkthdr ph; */
struct ffblk f;
/* struct date dd; */
/* struct time tt; */
/* Once created an empty poll packet. Left the code in (commented
out) in case you need them. What I do now is just create an empty
*.CLO file, which won't be routed on subsequent passes. */
lstrip(line);
stripcr(line);
rstrip(line);
p=strtok(line,":");
if(!p) return;
zone=(word)atol(p);
if(!zone) return;
p=strtok(0,"/");
if(!p) return;
net=(word)atol(p);
if(!net) return;
p=strtok(0,". ");
if(!p) return;
node=(word)atol(p);
/* if(strchr(p,'.')) {
p=strchr(p,'.');
p++;
point=(word)atol(p);
}
else point=0;
*/
/* The empty *.CLO creator */
if(zone!=myzone) sprintf(outbound,"%s\\.%03x",root,zone);
else strcpy(outbound,root);
sprintf(s,"%s\\%04x%04x.CLO",outbound,net,node);
if(findfirst(s,&f,0)) return;
fclose(fopen(s,"wb"));
printf("Created poll attach for %u:%u/%01u\n",zone,net,node);
return;
/* Code below is the empty packet creator, commented out... */
/*
pw=strtok(0,"\n "); */ /* Password if any */
/*
if(zone!=myzone) sprintf(outbound,"%s\\.%03x",root,zone);
else strcpy(outbound,root);
sprintf(s,"%s\\%04x%04x.CUT",outbound,net,node);
if(!findfirst(s,&f,0)) return;
fp=fopen(s,"wb");
if(!fp) {
fprintf(stderr,"\nCan't open poll packet `%s'\n",s);
return;
}
getdate(&dd);
gettime(&tt);
ph.orig_node=mynode;
ph.dest_node=node;
ph.year=dd.da_year;
ph.month=dd.da_mon;
ph.day=dd.da_day;
ph.hour=tt.ti_hour;
ph.minute=tt.ti_min;
ph.second=tt.ti_sec;
ph.rate=0;
ph.ver=2;
ph.orig_net=mynet;
ph.dest_net=net; */
/* ph.product=0; */ /* Until I get a product code (snore) */
/* ph.rev_lev=201; */ /* Well, it's gotta be something... */
/* strset(ph.password,0);
if(pw) strcpy(ph.password,pw);
ph.qm_orig_zone=myzone;
ph.qm_dest_zone=zone;
strset(ph.TRASH,0);
ph.orig_zone=myzone;
ph.dest_zone=zone;
ph.orig_point=mypoint;
ph.dest_point=point;
ph.pr_data=0L;
fwrite(&ph,sizeof(struct _pkthdr),1,fp);
printf("Created poll packet for %u:%u/%01u.%01u\n",zone,net,node,point);
fclose(fp);
*/
}
char * pascal stristr (char *t, char *s) {
char *t1;
char *s1;
/* Case-insensitive strstr()--Turbo C didn't have one */
while(*t) {
t1=t;
s1=s;
while(*s1) {
if (toupper(*s1)!=toupper(*t)) break;
else {
s1++;
t++;
}
}
if (!*s1) return t1;
t=t1+1;
}
return NULL;
}
char pascal spawnit (char *a) {
char *e[27],*p;
word x;
union REGS rg;
/* Handle spawning external programs (usually archivers)
Returns a valid exit code unless you call COMMAND.COM /c <batfile> */
*e=a;
p=a;
p=skip_nonwhite(p);
if(*p) {
*p=0;
p++;
p=skip_white(p);
}
for (x=1;x<25;x++) {
if(!*p) {
e[x]=NULL;
break;
}
e[x]=p;
p=skip_nonwhite(p);
if(*p) {
*p=0;
p++;
}
p=skip_white(p);
}
rg.x.ax=spawnvp(P_WAIT,a,e);
if (!rg.x.ax) {
rg.h.ah=77;
int86(0x21,&rg,&rg);
}
if (debug || more) printf("Exit status: %hu\n",rg.h.al);
return rg.h.al;
}
long pascal make_msgid (void) {
time_t t;
static word counter=0;
/* Create a msgid serial number, including a counter */
(void)time(&t);
t = (t<<4L) | (long)(counter++ & 15);
return t;
}
char * pascal find_sched (FILE *pf, char *schedtag, int wholefile) {
char *p;
char s[256];
/* Given a file pointer and schedule tag string, searches file for
schedule tag and returns it if found. Returns NULL if not. */
while(1) {
if(!fgets(s,256,pf)) {
if(wholefile) { /* Reset and try once more */
wholefile=0;
lines=0;
fseek(pf,0L,SEEK_SET);
continue;
}
fprintf(stderr,"\nRequested schedule tag '%s' not found.\n",schedtag);
return NULL;
}
lines++;
if(debug)printf("%u. %s",lines,s);
lstrip(s);
while(p=strchr(s,'\t')) *p=' ';
if(p=strchr(s,';')) *p=0;
p=s;
if(usingbink) {
if(strnicmp(p,"APPLICATION MAKEARC ",20)) continue; /* Not ours */
p+=20;
lstrip(p);
}
if(!strnicmp(p,"SCHED ",6)) {
p+=6;
lstrip(p);
stripcr(p);
rstrip(p);
if(!stricmp(p,schedtag)) {
printf("Processing schedule tag '%s'\n",schedtag);
break;
}
}
}
return p;
}
char * pascal skip_white (char *p) {
while(*p && (*p==' ' || *p=='\t')) *p++;
return p;
}
char * pascal skip_nonwhite (char *p) {
while(*p && *p!=' ' && *p!='\t')*p++;
return p;
}
char * pascal to_delim (char *p, char *delim) {
char *d;
while(*p) {
d=delim;
while(*d && *p!=*d) d++;
if(*p==*d) break;
p++;
}
return p;
}
char * pascal rstrip (char *a) { /* Remove trailing spaces and tabs */
register int x;
x=strlen(a);
while (x && a && (a[x-1]==' ' || a[x-1]=='\t')) a[--x]=0;
return a;
}
char * pascal lstrip (char *a) { /* Remove leading spaces and tabs */
register int x;
x=strlen(a);
while (x && (*a==' ' || *a=='\t')) memmove (a,(a+1),x--);
return (a);
}
char * pascal stripcr (char *a) { /* Remove trailing crs and lfs */
register int x;
x=strlen(a);
while (x && (a[x-1]=='\n' || a[x-1]=='\r')) a[--x]=0;
return a;
}
int cdecl hardware_error (int errnum,int ax,int bp,int si) {
union REGS rg;
struct SREGS sg;
char ch[]="\r\nA very fatal hardware error occured...shutting down now.\r\n$";
static int counter=0;
if(counter<12 && !didbreak) {
counter++;
hardresume(1); /* Retry 12 times */
}
/* State that error happened, we're closing up shop */
rg.x.ax=9;
rg.x.dx=FP_OFF(ch);
sg.ds=FP_SEG(ch);
int86x(0x21,&rg,&rg,&sg);
/* Report some info on error */
rg.x.ax=9;
if(ax>-1) sprintf(ch,"\r\nError was on drive %c:\r\n$",'A'+(char)(ax & 0xFF));
else sprintf(ch,"\r\nError was in driver at %d:%d\r\n$",bp,si);
rg.x.dx=FP_OFF(ch);
sg.ds=FP_SEG(ch);
int86x(0x21,&rg,&rg,&sg);
hardresume(2); /* Abort */
}
/*
Note that I left some commented out stuff in this that didn't work, but
you might find it a useful base from which to add more functions. At
least I did go through and put in some comments this time.
As always, you're on your own; goodnight.
*/